Conditions | 42 |
Paths | > 20000 |
Total Lines | 437 |
Lines | 0 |
Ratio | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like ajax.js ➔ ... ➔ jQuery.extend.ajax often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | define( [ |
||
386 | ajax: function( url, options ) { |
||
387 | |||
388 | // If url is an object, simulate pre-1.5 signature |
||
389 | if ( typeof url === "object" ) { |
||
390 | options = url; |
||
391 | url = undefined; |
||
392 | } |
||
393 | |||
394 | // Force options to be an object |
||
395 | options = options || {}; |
||
396 | |||
397 | var transport, |
||
398 | |||
399 | // URL without anti-cache param |
||
400 | cacheURL, |
||
401 | |||
402 | // Response headers |
||
403 | responseHeadersString, |
||
404 | responseHeaders, |
||
405 | |||
406 | // timeout handle |
||
407 | timeoutTimer, |
||
408 | |||
409 | // Url cleanup var |
||
410 | urlAnchor, |
||
411 | |||
412 | // Request state (becomes false upon send and true upon completion) |
||
413 | completed, |
||
414 | |||
415 | // To know if global events are to be dispatched |
||
416 | fireGlobals, |
||
417 | |||
418 | // Loop variable |
||
419 | i, |
||
420 | |||
421 | // uncached part of the url |
||
422 | uncached, |
||
423 | |||
424 | // Create the final options object |
||
425 | s = jQuery.ajaxSetup( {}, options ), |
||
426 | |||
427 | // Callbacks context |
||
428 | callbackContext = s.context || s, |
||
429 | |||
430 | // Context for global events is callbackContext if it is a DOM node or jQuery collection |
||
431 | globalEventContext = s.context && |
||
432 | ( callbackContext.nodeType || callbackContext.jquery ) ? |
||
433 | jQuery( callbackContext ) : |
||
434 | jQuery.event, |
||
435 | |||
436 | // Deferreds |
||
437 | deferred = jQuery.Deferred(), |
||
438 | completeDeferred = jQuery.Callbacks( "once memory" ), |
||
439 | |||
440 | // Status-dependent callbacks |
||
441 | statusCode = s.statusCode || {}, |
||
442 | |||
443 | // Headers (they are sent all at once) |
||
444 | requestHeaders = {}, |
||
445 | requestHeadersNames = {}, |
||
446 | |||
447 | // Default abort message |
||
448 | strAbort = "canceled", |
||
449 | |||
450 | // Fake xhr |
||
451 | jqXHR = { |
||
452 | readyState: 0, |
||
453 | |||
454 | // Builds headers hashtable if needed |
||
455 | getResponseHeader: function( key ) { |
||
456 | var match; |
||
457 | if ( completed ) { |
||
458 | if ( !responseHeaders ) { |
||
459 | responseHeaders = {}; |
||
460 | while ( ( match = rheaders.exec( responseHeadersString ) ) ) { |
||
461 | responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; |
||
462 | } |
||
463 | } |
||
464 | match = responseHeaders[ key.toLowerCase() ]; |
||
465 | } |
||
466 | return match == null ? null : match; |
||
467 | }, |
||
468 | |||
469 | // Raw string |
||
470 | getAllResponseHeaders: function() { |
||
471 | return completed ? responseHeadersString : null; |
||
472 | }, |
||
473 | |||
474 | // Caches the header |
||
475 | setRequestHeader: function( name, value ) { |
||
476 | if ( completed == null ) { |
||
477 | name = requestHeadersNames[ name.toLowerCase() ] = |
||
478 | requestHeadersNames[ name.toLowerCase() ] || name; |
||
479 | requestHeaders[ name ] = value; |
||
480 | } |
||
481 | return this; |
||
482 | }, |
||
483 | |||
484 | // Overrides response content-type header |
||
485 | overrideMimeType: function( type ) { |
||
486 | if ( completed == null ) { |
||
487 | s.mimeType = type; |
||
488 | } |
||
489 | return this; |
||
490 | }, |
||
491 | |||
492 | // Status-dependent callbacks |
||
493 | statusCode: function( map ) { |
||
494 | var code; |
||
495 | if ( map ) { |
||
496 | if ( completed ) { |
||
497 | |||
498 | // Execute the appropriate callbacks |
||
499 | jqXHR.always( map[ jqXHR.status ] ); |
||
500 | } else { |
||
501 | |||
502 | // Lazy-add the new callbacks in a way that preserves old ones |
||
503 | for ( code in map ) { |
||
504 | statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; |
||
505 | } |
||
506 | } |
||
507 | } |
||
508 | return this; |
||
509 | }, |
||
510 | |||
511 | // Cancel the request |
||
512 | abort: function( statusText ) { |
||
513 | var finalText = statusText || strAbort; |
||
514 | if ( transport ) { |
||
515 | transport.abort( finalText ); |
||
516 | } |
||
517 | done( 0, finalText ); |
||
518 | return this; |
||
519 | } |
||
520 | }; |
||
521 | |||
522 | // Attach deferreds |
||
523 | deferred.promise( jqXHR ); |
||
524 | |||
525 | // Add protocol if not provided (prefilters might expect it) |
||
526 | // Handle falsy url in the settings object (#10093: consistency with old signature) |
||
527 | // We also use the url parameter if available |
||
528 | s.url = ( ( url || s.url || location.href ) + "" ) |
||
529 | .replace( rprotocol, location.protocol + "//" ); |
||
530 | |||
531 | // Alias method option to type as per ticket #12004 |
||
532 | s.type = options.method || options.type || s.method || s.type; |
||
533 | |||
534 | // Extract dataTypes list |
||
535 | s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; |
||
536 | |||
537 | // A cross-domain request is in order when the origin doesn't match the current origin. |
||
538 | if ( s.crossDomain == null ) { |
||
539 | urlAnchor = document.createElement( "a" ); |
||
540 | |||
541 | // Support: IE <=8 - 11, Edge 12 - 13 |
||
542 | // IE throws exception on accessing the href property if url is malformed, |
||
543 | // e.g. http://example.com:80x/ |
||
544 | try { |
||
545 | urlAnchor.href = s.url; |
||
546 | |||
547 | // Support: IE <=8 - 11 only |
||
548 | // Anchor's host property isn't correctly set when s.url is relative |
||
549 | urlAnchor.href = urlAnchor.href; |
||
550 | s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== |
||
551 | urlAnchor.protocol + "//" + urlAnchor.host; |
||
552 | } catch ( e ) { |
||
553 | |||
554 | // If there is an error parsing the URL, assume it is crossDomain, |
||
555 | // it can be rejected by the transport if it is invalid |
||
556 | s.crossDomain = true; |
||
557 | } |
||
558 | } |
||
559 | |||
560 | // Convert data if not already a string |
||
561 | if ( s.data && s.processData && typeof s.data !== "string" ) { |
||
562 | s.data = jQuery.param( s.data, s.traditional ); |
||
563 | } |
||
564 | |||
565 | // Apply prefilters |
||
566 | inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); |
||
567 | |||
568 | // If request was aborted inside a prefilter, stop there |
||
569 | if ( completed ) { |
||
570 | return jqXHR; |
||
571 | } |
||
572 | |||
573 | // We can fire global events as of now if asked to |
||
574 | // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) |
||
575 | fireGlobals = jQuery.event && s.global; |
||
576 | |||
577 | // Watch for a new set of requests |
||
578 | if ( fireGlobals && jQuery.active++ === 0 ) { |
||
579 | jQuery.event.trigger( "ajaxStart" ); |
||
580 | } |
||
581 | |||
582 | // Uppercase the type |
||
583 | s.type = s.type.toUpperCase(); |
||
584 | |||
585 | // Determine if request has content |
||
586 | s.hasContent = !rnoContent.test( s.type ); |
||
587 | |||
588 | // Save the URL in case we're toying with the If-Modified-Since |
||
589 | // and/or If-None-Match header later on |
||
590 | // Remove hash to simplify url manipulation |
||
591 | cacheURL = s.url.replace( rhash, "" ); |
||
592 | |||
593 | // More options handling for requests with no content |
||
594 | if ( !s.hasContent ) { |
||
595 | |||
596 | // Remember the hash so we can put it back |
||
597 | uncached = s.url.slice( cacheURL.length ); |
||
598 | |||
599 | // If data is available, append data to url |
||
600 | if ( s.data ) { |
||
601 | cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; |
||
602 | |||
603 | // #9682: remove data so that it's not used in an eventual retry |
||
604 | delete s.data; |
||
605 | } |
||
606 | |||
607 | // Add or update anti-cache param if needed |
||
608 | if ( s.cache === false ) { |
||
609 | cacheURL = cacheURL.replace( rantiCache, "$1" ); |
||
610 | uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; |
||
611 | } |
||
612 | |||
613 | // Put hash and anti-cache on the URL that will be requested (gh-1732) |
||
614 | s.url = cacheURL + uncached; |
||
615 | |||
616 | // Change '%20' to '+' if this is encoded form body content (gh-2658) |
||
617 | } else if ( s.data && s.processData && |
||
618 | ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { |
||
619 | s.data = s.data.replace( r20, "+" ); |
||
620 | } |
||
621 | |||
622 | // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
||
623 | if ( s.ifModified ) { |
||
624 | if ( jQuery.lastModified[ cacheURL ] ) { |
||
625 | jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); |
||
626 | } |
||
627 | if ( jQuery.etag[ cacheURL ] ) { |
||
628 | jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); |
||
629 | } |
||
630 | } |
||
631 | |||
632 | // Set the correct header, if data is being sent |
||
633 | if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { |
||
634 | jqXHR.setRequestHeader( "Content-Type", s.contentType ); |
||
635 | } |
||
636 | |||
637 | // Set the Accepts header for the server, depending on the dataType |
||
638 | jqXHR.setRequestHeader( |
||
639 | "Accept", |
||
640 | s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? |
||
641 | s.accepts[ s.dataTypes[ 0 ] ] + |
||
642 | ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : |
||
643 | s.accepts[ "*" ] |
||
644 | ); |
||
645 | |||
646 | // Check for headers option |
||
647 | for ( i in s.headers ) { |
||
648 | jqXHR.setRequestHeader( i, s.headers[ i ] ); |
||
649 | } |
||
650 | |||
651 | // Allow custom headers/mimetypes and early abort |
||
652 | if ( s.beforeSend && |
||
653 | ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { |
||
654 | |||
655 | // Abort if not done already and return |
||
656 | return jqXHR.abort(); |
||
657 | } |
||
658 | |||
659 | // Aborting is no longer a cancellation |
||
660 | strAbort = "abort"; |
||
661 | |||
662 | // Install callbacks on deferreds |
||
663 | completeDeferred.add( s.complete ); |
||
664 | jqXHR.done( s.success ); |
||
665 | jqXHR.fail( s.error ); |
||
666 | |||
667 | // Get transport |
||
668 | transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); |
||
669 | |||
670 | // If no transport, we auto-abort |
||
671 | if ( !transport ) { |
||
672 | done( -1, "No Transport" ); |
||
673 | } else { |
||
674 | jqXHR.readyState = 1; |
||
675 | |||
676 | // Send global event |
||
677 | if ( fireGlobals ) { |
||
678 | globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); |
||
679 | } |
||
680 | |||
681 | // If request was aborted inside ajaxSend, stop there |
||
682 | if ( completed ) { |
||
683 | return jqXHR; |
||
684 | } |
||
685 | |||
686 | // Timeout |
||
687 | if ( s.async && s.timeout > 0 ) { |
||
688 | timeoutTimer = window.setTimeout( function() { |
||
689 | jqXHR.abort( "timeout" ); |
||
690 | }, s.timeout ); |
||
691 | } |
||
692 | |||
693 | try { |
||
694 | completed = false; |
||
695 | transport.send( requestHeaders, done ); |
||
696 | } catch ( e ) { |
||
697 | |||
698 | // Rethrow post-completion exceptions |
||
699 | if ( completed ) { |
||
700 | throw e; |
||
701 | } |
||
702 | |||
703 | // Propagate others as results |
||
704 | done( -1, e ); |
||
705 | } |
||
706 | } |
||
707 | |||
708 | // Callback for when everything is done |
||
709 | function done( status, nativeStatusText, responses, headers ) { |
||
710 | var isSuccess, success, error, response, modified, |
||
711 | statusText = nativeStatusText; |
||
712 | |||
713 | // Ignore repeat invocations |
||
714 | if ( completed ) { |
||
715 | return; |
||
716 | } |
||
717 | |||
718 | completed = true; |
||
719 | |||
720 | // Clear timeout if it exists |
||
721 | if ( timeoutTimer ) { |
||
722 | window.clearTimeout( timeoutTimer ); |
||
723 | } |
||
724 | |||
725 | // Dereference transport for early garbage collection |
||
726 | // (no matter how long the jqXHR object will be used) |
||
727 | transport = undefined; |
||
728 | |||
729 | // Cache response headers |
||
730 | responseHeadersString = headers || ""; |
||
731 | |||
732 | // Set readyState |
||
733 | jqXHR.readyState = status > 0 ? 4 : 0; |
||
734 | |||
735 | // Determine if successful |
||
736 | isSuccess = status >= 200 && status < 300 || status === 304; |
||
737 | |||
738 | // Get response data |
||
739 | if ( responses ) { |
||
740 | response = ajaxHandleResponses( s, jqXHR, responses ); |
||
741 | } |
||
742 | |||
743 | // Convert no matter what (that way responseXXX fields are always set) |
||
744 | response = ajaxConvert( s, response, jqXHR, isSuccess ); |
||
745 | |||
746 | // If successful, handle type chaining |
||
747 | if ( isSuccess ) { |
||
748 | |||
749 | // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
||
750 | if ( s.ifModified ) { |
||
751 | modified = jqXHR.getResponseHeader( "Last-Modified" ); |
||
752 | if ( modified ) { |
||
753 | jQuery.lastModified[ cacheURL ] = modified; |
||
754 | } |
||
755 | modified = jqXHR.getResponseHeader( "etag" ); |
||
756 | if ( modified ) { |
||
757 | jQuery.etag[ cacheURL ] = modified; |
||
758 | } |
||
759 | } |
||
760 | |||
761 | // if no content |
||
762 | if ( status === 204 || s.type === "HEAD" ) { |
||
763 | statusText = "nocontent"; |
||
764 | |||
765 | // if not modified |
||
766 | } else if ( status === 304 ) { |
||
767 | statusText = "notmodified"; |
||
768 | |||
769 | // If we have data, let's convert it |
||
770 | } else { |
||
771 | statusText = response.state; |
||
772 | success = response.data; |
||
773 | error = response.error; |
||
774 | isSuccess = !error; |
||
775 | } |
||
776 | } else { |
||
777 | |||
778 | // Extract error from statusText and normalize for non-aborts |
||
779 | error = statusText; |
||
780 | if ( status || !statusText ) { |
||
781 | statusText = "error"; |
||
782 | if ( status < 0 ) { |
||
783 | status = 0; |
||
784 | } |
||
785 | } |
||
786 | } |
||
787 | |||
788 | // Set data for the fake xhr object |
||
789 | jqXHR.status = status; |
||
790 | jqXHR.statusText = ( nativeStatusText || statusText ) + ""; |
||
791 | |||
792 | // Success/Error |
||
793 | if ( isSuccess ) { |
||
794 | deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); |
||
795 | } else { |
||
796 | deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); |
||
797 | } |
||
798 | |||
799 | // Status-dependent callbacks |
||
800 | jqXHR.statusCode( statusCode ); |
||
801 | statusCode = undefined; |
||
802 | |||
803 | if ( fireGlobals ) { |
||
804 | globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", |
||
805 | [ jqXHR, s, isSuccess ? success : error ] ); |
||
806 | } |
||
807 | |||
808 | // Complete |
||
809 | completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); |
||
810 | |||
811 | if ( fireGlobals ) { |
||
812 | globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); |
||
813 | |||
814 | // Handle the global AJAX counter |
||
815 | if ( !( --jQuery.active ) ) { |
||
816 | jQuery.event.trigger( "ajaxStop" ); |
||
817 | } |
||
818 | } |
||
819 | } |
||
820 | |||
821 | return jqXHR; |
||
822 | }, |
||
823 | |||
856 |